/************************************************************************
 * File: board.cpp                                                      *
 *                                                                      *
 * Copyright 2006, 2008 Colin Kern (colin.kern@gmail.com)               *
 *                                                                      *
 * This file is part of Profit.  Some previous versions were released   *
 * under the names Megacorp Mania and Acquire.                          *
 *                                                                      *
 * Profit is free software: you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public License as published by *
 * the Free Software Foundation, either version 3 of the License, or    *
 * any later version.                                                   *
 *                                                                      *
 * Profit is distributed in the hope that it will be useful,            *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 * GNU General Public License for more details.                         *
 *                                                                      *
 * You should have received a copy of the GNU General Public License    *
 * along with Profit.  If not, see <http://www.gnu.org/licenses/>.      *
 ************************************************************************/
#include "board.h"
#include "boardslot.h"
#include "tile.h"
#include <QList>
#include <QPainter>
#include <QGridLayout>

Board::Board(int rows, int columns, QWidget *parent)
	: QWidget(parent)
{
	QGridLayout *layout = new QGridLayout;
	for (int i = 0; i < rows; ++i) {
		m_board.append(QList<BoardSlot*>());
		for (int j = 0;  j < columns; ++j) {
			m_board[i].append(new BoardSlot(i, j));
			layout->addWidget(m_board[i].last(), i, j);
			connect(m_board[i].last(), SIGNAL(clicked(int, int)),
				this, SIGNAL(slotClicked(int, int)));
		}
	}
	layout->setSpacing(1);
	
	setLayout(layout);
	setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}

const BoardSlot *Board::getSlot(int row, int column) const
{
    return m_board.at(row).at(column);
}

int Board::nRows() const
{
  return m_board.size();
}

int Board::nColumns() const
{
  return m_board.at(0).size();
}

QSize Board::sizeHint() const
{
	return QSize(BoardSlot::Width * nColumns(), BoardSlot::Height * nRows());
}

BoardSlot *Board::getSlot(int row, int column)
{
    return m_board[row][column];
}

BoardSlot *Board::getSlot(const Tile &tile)
{
	return getSlot(tile.getRow(), tile.getColumn());
}

void Board::reset()
{
	for (int row = 0; row < nRows(); ++row) {
		for (int column = 0; column < nColumns(); ++column) {
			getSlot(row, column)->remove();
		}
	}
}

void Board::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	
	QLinearGradient gradient(rect().topLeft(), rect().bottomRight());
	gradient.setColorAt(0.0, Qt::darkGray);
	gradient.setColorAt(1.0, QColor(96, 96, 96));
	
	painter.setBrush(QBrush(gradient));
	painter.setPen(Qt::NoPen);
	painter.drawRect(rect());
}

void Board::highlightTile(const Tile &tile, BoardSlot::Highlight highlight)
{
	getSlot(tile)->setHighlight(highlight);
}

void Board::removeTile(const Tile &tile, bool invisible)
{
	getSlot(tile)->remove(invisible);
	m_moves.removeAll(tile);
}

QList<Tile> Board::placeTile(const Tile &tile, bool invisible)
{
    QList<Tile> adjacents;
    
    getSlot(tile)->place(invisible);

    adjacents = adjacent(tile);
      
    // Unflag all slots
    for (int row = 0; row < nRows(); ++row) {
        for (int column = 0; column < nColumns(); ++column) {
            getSlot(row, column)->unflag();
		}
	}
    
	m_moves.append(tile);

    return adjacents;
}

QList<Tile> Board::adjacent(const Tile &tile)
{
    QList<Tile> adjacents;
    
	if (tile.getRow() < 0 || tile.getRow() >= nRows() ||
		tile.getColumn() < 0 || tile.getColumn() >= nColumns()) {
		return adjacents;
	}
	
	if (!getSlot(tile)->isPlaced() || getSlot(tile)->isFlagged()) {
		return adjacents;
	}
	
    adjacents.append(tile);

    getSlot(tile)->flag();

	adjacents << adjacent(tile.above())
			<< adjacent(tile.below())
			<< adjacent(tile.left())
			<< adjacent(tile.right());
    
    return adjacents;
}

QList<Company*> Board::findCompanies(const QList<Tile> &tiles)
{
	QList<Company*> companies;
    BoardSlot *slot;
	
    QListIterator<Tile> i(tiles);
	while (i.hasNext()) {
		slot = getSlot(i.next());
		
        if (slot->isOwned() && !companies.contains(slot->getOwner())) {
            companies.append(slot->getOwner());
        }
    }
    
    return companies;
}

void Board::clearHighlights()
{
	for (int row = 0; row < nRows(); ++row) {
        for (int column = 0; column < nColumns(); ++column) {
			getSlot(row, column)->setHighlight(BoardSlot::None);
		}
	}
}
